package com.qgs.secsgem.secs.eqsimulator;

import com.qgs.secsgem.secs.SecsCommunicator;
import com.qgs.secsgem.secs.SecsException;
import com.qgs.secsgem.secs.SecsMessage;
import com.qgs.secsgem.secs.gem.*;
import com.qgs.secsgem.secs.hsmsss.HsmsSsCommunicator;
import com.qgs.secsgem.secs.hsmsss.HsmsSsCommunicatorConfig;
import com.qgs.secsgem.secs.hsmsss.HsmsSsProtocol;
import com.qgs.secsgem.secs.secs2.Secs2;
import com.qgs.secsgem.secs.secs2.Secs2Binary;
import com.qgs.secsgem.secs.secs2.Secs2Exception;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.InetSocketAddress;

@Component
public class PID24aSimulator {
    private HsmsSsCommunicatorConfig config = new HsmsSsCommunicatorConfig();
    private String hostname = "127.0.0.1";
    private Integer port = 5000;
    private SecsCommunicator comm;


    public SecsCommunicator getComm(){
        return comm;
    }

    PID24aSimulator() {
        config.socketAddress(new InetSocketAddress(hostname, port));
        config.protocol(HsmsSsProtocol.PASSIVE);
        config.sessionId(0);
        config.isEquip(true);
        config.notLinktest();
        config.timeout().t3(45.0F);
        config.timeout().t6( 5.0F);
        config.timeout().t7(10.0F);
        config.timeout().t8( 6.0F);
        config.gem().mdln("MDLN-A");
        config.gem().softrev("000001");


        comm = HsmsSsCommunicator.newInstance(config);


        //日志的回调接口
        comm.addSecsLogListener(l->{
            System.err.println("{\nPID24a EAP Client : \n"+l+"\n}");
        });

        comm.addSecsMessageReceiveListener(msg -> {

            try {

                if ( msg.sessionId() != config.sessionId().intValue() ) {
                    comm.gem().s9f1(msg);
                    return;
                }

                response(comm, msg);

            }
            catch ( InterruptedException ignore ) {
            }
            catch ( SecsException e) {
                e.printStackTrace();
            }
        });

        comm.addSecsCommunicatableStateChangeListener(state -> {
            System.out.println(state);
            //这里主要是做一些初始化的动作。S1F13+S1F17+...

            if ( state /* SELECTED */ ) {
                //S6F11不能放在这里
//						System.out.println("PID10 state："+state);
//						//向设备发起S1F13事件，请求建立通联连接
//						{
//							/* build <L[0] > */
//							Secs2 ss = Secs2.list(
//									Secs2.int4(1)         //MDLN
//									, Secs2.int4(1001)    //SOFTREV
//							);
//
//							/* send s1f13 <L[0] > */
//							comm.send(1, 13, true, ss);
//						}

//                    {
//                        //build s6f11
//                        Secs2 s6f11 = Secs2.list(
//                                Secs2.uint4(1)      //dataid
//                                , Secs2.int4(21)  //ceid
//                                , Secs2.list(
//                                        Secs2.list(
//                                                Secs2.uint4(10171),  //reportId
//                                                Secs2.list(
//                                                        Secs2.ascii("2024081600000025")
//                                                        ,Secs2.float4(1329.21f)
//                                                )
//                                        )
//                                )
//                        );
//                        System.out.println("s6f11 is ready to send: \n"+s6f11.toString());
//                        try {
//                            comm.send(6,11,true,s6f11);
//                        }catch (Exception e){
//
//                        }
//                        System.out.println("s6f11 is sended: \n"+s6f11.toString());
//                    }
            }
        });

        try {
            comm.open();

        }catch (Exception e){
            e.printStackTrace();
        }
    }


    private static void response(SecsCommunicator comm, SecsMessage msg)
            throws InterruptedException, SecsException {

        int strm = msg.getStream();
        int func = msg.getFunction();
        boolean wbit = msg.wbit();
        Secs2 secs2 = msg.secs2();

        try {

            switch ( strm ) {
                case 1: {

                    switch ( func ) {
                        case 1: {

                            if ( wbit ) {
                                comm.gem().s1f2(msg);
                            }
                            break;
                        }
                        case 13: {

                            if ( wbit ) {
                                comm.gem().s1f14(msg, COMMACK.OK);
                            }
                            break;
                        }
                        case 15: {

                            if ( wbit ) {
                                comm.gem().s1f16(msg);
                            }
                            break;
                        }
                        case 17: {

                            if ( wbit ) {
                                comm.gem().s1f18(msg, ONLACK.OK);
                            }
                            break;
                        }
                        default: {

                            if ( wbit ) {
                                comm.send(msg, strm, 0, false);
                            }

                            comm.gem().s9f5(msg);
                        }
                    }

                    break;
                }

                case 2: {

                    switch ( func ) {

                        case 21: {

                            String rcmd = secs2.getAscii();
                            System.out.println(rcmd);

                            if ( wbit ) {
                                comm.gem().s2f22(msg, CMDA.CommandDoesNotExist);
                            }
                            break;
                        }

                        case 31: {

                            String time = secs2.getAscii();
                            System.out.println(time);

                            if ( wbit ) {
                                comm.gem().s2f32(msg, TIACK.OK);
                            }
                            break;
                        }
                        case 33: {

                            if ( wbit ) {
                                comm.gem().s2f34(msg,DRACK.OK);
                            }
                            break;
                        }
                        case 35: {

                            if ( wbit ) {
                                comm.gem().s2f36(msg,LRACK.OK);
                            }
                            break;
                        }
                        case 37: {

                            if ( wbit ) {
                                comm.gem().s2f38(msg,ERACK.OK);
                            }
                            break;
                        }
                        default: {

                            if ( wbit ) {
                                comm.send(msg, strm, 0, false);
                            }

                            comm.gem().s9f5(msg);
                        }
                    }

                    break;
                }
                case 6: {
                    switch ( func ) {
                        case 23: {
                            if ( wbit ) {
                                //RSDC binary
                                comm.send(msg, 6, 24, false,Secs2.binary((byte) 0));
                            }
                            break;
                        }
                        default: {
                            if ( wbit ) {
                                comm.send(msg, strm, 0, false);
                            }
                            comm.gem().s9f5(msg);
                        }
                    }
                    break;
                }

                case 10: {

                    switch ( func ) {
                        case 3: {

                            /*
                             * Terminal Display, Single-Block
                             * format
                             * S10F3 W
                             * <L
                             *   <B[1] TID>
                             *   <A[n] display-text>
                             * >
                             */

                            String dispText = secs2.getAscii(1);

                            System.out.println(dispText);

                            if ( wbit ) {
                                comm.gem().s10f4(msg, ACKC10.AcceptedForDisplay);
                            }
                            break;
                        }
                        case 5: {

                            /*
                             * Terminal Display, Multi-Block
                             * format:
                             * S10F5 W
                             * <L
                             *   <B[1] TID>
                             *   <L[n]
                             *     <A block-1>
                             *     <A block-2>
                             *     ...
                             *   >
                             * >
                             */

                            Secs2 ss = secs2.get(1);

                            /* AbstractSecs2 implements Iterable */
                            for ( Secs2 s : ss ) {
                                String dispText = s.getAscii();
                                System.out.println(dispText);
                            }

                            if ( wbit ) {
                                comm.gem().s10f6(msg, ACKC10.AcceptedForDisplay);
                            }

                            break;
                        }
                        default: {

                            if ( wbit ) {
                                comm.send(msg, strm, 0, false);
                            }

                            comm.gem().s9f5(msg);
                        }
                    }

                    break;
                }

                default: {

                    if ( wbit ) {
                        comm.send(msg, strm, 0, false);
                    }

                    comm.gem().s9f3(msg);
                }
            }
        }
        catch ( Secs2Exception e ) {

            comm.gem().s9f7(msg);
        }
    }



}
